﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufImpl.h"
#include "GnufINotificationCenterEventArgs.h"

namespace gnuf 
{
    class Process;

    namespace impl
    {
        class GNUF_IMPL_CLASS(ProcessManager);
    }

    class GNUF_BASE_EXPORT ProcessEventArgs final : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ProcessEventArgs, INotificationCenterEventArgs)
    public:
        enum class Status
        {
            eStartFailue,
            eExitSucceed,
            eCrash,
            eTimedout,
            eReadError,
            eWriteError,
            eUnknownError
        };
        explicit ProcessEventArgs(Status status, int exitCode, long long processId, const std::wstring& processPath);
        ~ProcessEventArgs() {}

        Status status() const { return m_status; }
        int exitCode() const { return m_exitCode; }
        long long processId() const { return m_processId; }
        const std::wstring& processPath() const { return m_processPath; }

    private:
        const Status m_status;
        const int m_exitCode = -1;
        const long long m_processId = -1;
        const std::wstring m_processPath;
    };

    class GNUF_BASE_EXPORT ProcessManager final
    {
        GNUF_IMPL_USE(ProcessManager);

    public:
        /**
        * @brief 进程信息 - {进程id, 进程别名, 进程路径}
        */
        using ProcessInfo = std::tuple<long long, std::wstring, std::wstring>;

        static ProcessManager * get();
        ProcessManager();
        ~ProcessManager();
        
    public:
        /**
        * @brief 启动进程
        * @param[in] processPath 进程路径
        * @param[in] cmdArgs 进程命令行启动参数
        * @param[in] exclusive 进程是否互斥启动的，即exclusive=true时,若将启动的进程已启动，则不会启动该进程
        * @param[in] alias 进程别名，不唯一。 alias默认值为processPath
        * @return 进程id，-1代表启动失败， 若exclusive=true的情况下，返回已经启动的进程id
        */
        long long startProcess(const std::wstring& processPath, const std::wstring& cmdArgs, bool exclusive, const std::wstring& alias = L"");

        /**
        * @brief 通过进程id, 结束进程
        * @param[in] processId 待结束进程的进程id
        * @return void
        */
        void terminateProcess(long long processId);

        /**
        * @brief 通过别名, 结束所有具有该别名的进程
        * @param[in] alias 待结束进程的别名
        * @return void
        */
        void terminateProcess(const std::wstring& alias);

        /**
        * @brief 杀死所有进程
        */
        void killAll();

        /**
        * @brief 进程是否在运行
        * @param[in] processId 进程id
        * @return true:正在运行 false:未运行
        */
        bool isRunning(long long processId) const;

        /**
        * @brief 该别名下的进程是否在运行
        * 别名并不是唯一的，取决于使用者的别名管理策略。
        * 使用此方法确定指定进程是否运行是不安全的。
        * @param[in] alias 进程别名
        * @return true:正在运行 false:未运行
        */
        bool isRunning(const std::wstring& alias) const;

        /**
        * @brief 获取所有的进程信息
        * @return 所有进程的信息列表
        * @see gnuf::ProcessManager::ProcessInfo
        */
        std::list<ProcessInfo> getAllProcessInfo() const;

    private:
        ProcessManager(const ProcessManager&) = delete;
        ProcessManager& operator=(const ProcessManager&) = delete;
    };
}

